package list

import (
	"fmt"

	"gitee.com/ekit/internal/errs"
)

type Node[T any] struct {
	data T
	next *Node[T]
}

type LinkListed[T any] struct {
	head   *Node[T]
	length int
}

func NewLinkListed[T any]() *LinkListed[T] {
	head := &Node[T]{}
	return &LinkListed[T]{
		head: head,
	}
}

// 将切片转化为链表
func NewLinkListedOf[T any](src []T) *LinkListed[T] {
	l := &LinkListed[T]{}
	l.Append(src...)
	return l
}

// 向链表中添加元素
func (l *LinkListed[T]) Append(ts ...T) error {
	cur := l.head
	for _, t := range ts {
		if l.length == 0 {
			cur.data = t
			l.length++
			continue
		}
		node := &Node[T]{data: t, next: nil}
		cur.next = node
		cur = node
		l.length++
	}
	return nil
}

// Add 根据位置， 向链表中添加数据
func (l *LinkListed[T]) Add(index int, element T) error {
	// 1.越界判断
	if index > l.length || index < 0 {
		return errs.NewErrIndexOutOfRange(l.length, index)
	}

	// 2.循环获取index位置的前一个node
	cur := l.head
	for i := 0; i < index; i++ {
		node := cur.next
		cur = node
	}
	// 3.记录当前元素的值， 添加元素， 并增加length值
	next := cur.next
	cur.next = &Node[T]{data: element, next: next}
	l.length++
	return nil
}

// Pop 删除链表中的最后一个元素
func (l *LinkListed[T]) Pop() (T, error) {
	var zero T
	cur := l.head
	for cur.next.next != nil {
		node := cur.next
		cur = node
	}
	zero = cur.next.data
	cur.next = nil
	l.length--
	return zero, nil
}

// Delete 根据元素的位置删除元素
func (l *LinkListed[T]) Delete(index int) (T, error) {
	var zero T
	// 1.边界判断
	if index > l.length || index < 0 {
		return zero, errs.NewErrIndexOutOfRange(l.length, index)
	}

	// 2.记录当前值和上一个node值
	cur := l.head
	prev := l.head
	for i := 0; i < index; i++ {
		node := cur.next
		prev = cur
		cur = node
	}
	// 3. 找到要删除的值， length--
	prev.next = cur.next
	zero = cur.data
	l.length--
	return zero, nil
}

// Length 返回链表的长度
func (l *LinkListed[T]) Length() int {
	return l.length
}

// Print 打印出所有的链表元素值
func (l *LinkListed[T]) Print() {
	cur := l.head
	for cur != nil {
		fmt.Println(cur.data)
	}
}
